package com.yht.weblog.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yht.weblog.admin.model.vo.dashboard.FindDashboardPVStatisticsInfoRspVO;
import com.yht.weblog.admin.model.vo.dashboard.FindDashboardStatisticsInfoRspVO;
import com.yht.weblog.admin.service.AdminDashboardService;
import com.yht.weblog.common.constants.Constants;
import com.yht.weblog.common.domain.dos.ArticleDO;
import com.yht.weblog.common.domain.dos.ArticlePublishCountDO;
import com.yht.weblog.common.domain.dos.StatisticsArticlePVDO;
import com.yht.weblog.common.domain.mapper.ArticleMapper;
import com.yht.weblog.common.domain.mapper.CategoryMapper;
import com.yht.weblog.common.domain.mapper.StatisticsArticlePVMapper;
import com.yht.weblog.common.domain.mapper.TagMapper;
import com.yht.weblog.common.utils.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: yht
 * @date: 2024/1/28 10:40
 * @description:
 **/
@Service
@Slf4j
public class AdminDashboardServiceImpl implements AdminDashboardService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private StatisticsArticlePVMapper articlePVMapper;

    /**
     * 查询仪表盘统计信息
     *
     * @return Response对象
     */
    @Override
    public Response findDashboardStatistics() {

        // 查询文章总数
        Long articleTotalCount = articleMapper.selectCount(Wrappers.emptyWrapper());
        // 查询分类总数
        Long categoryTotalCount = categoryMapper.selectCount(Wrappers.emptyWrapper());
        // 查询标签总数
        Long tagTotalCount = tagMapper.selectCount(Wrappers.emptyWrapper());
        // 查询所有文章的阅读数
        List<ArticleDO> articleDOS = articleMapper.selectAllReadNum();
        // 统计文章的阅读总数
        Long pvTotalCount = 0L;
        if (!CollectionUtils.isEmpty(articleDOS)) {
            // 所有文章的阅读数相加
            pvTotalCount = articleDOS.stream().mapToLong(ArticleDO::getReadNum).sum();
        }

        // 构建响应数据
        FindDashboardStatisticsInfoRspVO vo = FindDashboardStatisticsInfoRspVO.builder()
                .articleTotalCount(articleTotalCount)
                .categoryTotalCount(categoryTotalCount)
                .tagTotalCount(tagTotalCount)
                .pvTotalCount(pvTotalCount)
                .build();

        // 返回响应结果
        return Response.success(vo);
    }

    /**
     * 查询仪表盘文章发布统计信息
     *
     * @return 包含日期与对应文章发布数量的映射关系的Response对象
     */
    @Override
    public Response findDashboardPublishArticleStatistics() {
        LocalDate currDate = LocalDate.now();  // 获取当前日期
        LocalDate startDate = currDate.minusYears(1);  // 获取去年同期日期

        List<ArticlePublishCountDO> articlePublishCountDOS = articleMapper.selectDateArticlePublishCount(startDate, currDate);  // 查询指定日期范围内（去年同期至当前）的文章发布数量信息

        Map<LocalDate, Long> map = null;  // 初始化一个用于存储日期与文章发布数量的映射关系的Map对象

        if (!CollectionUtils.isEmpty(articlePublishCountDOS)) {  // 如果查询结果不为空
            Map<LocalDate, Long> dateArticleCountMap = articlePublishCountDOS.stream()  // 将查询结果转换为日期到文章发布数量的映射关系
                    .collect(Collectors.toMap(ArticlePublishCountDO::getDate, ArticlePublishCountDO::getCount));
            map = Maps.newLinkedHashMap();  // 创建一个新的有序的日期与文章发布数量的映射关系

            for (; startDate.isBefore(currDate) || startDate.isEqual(currDate); startDate = startDate.plusDays(1)) {  // 遍历从去年同期到当前日期的每一天
                Long count = dateArticleCountMap.get(startDate);  // 获取当前日期对应的文章发布数量
                map.put(startDate, Objects.isNull(count) ? 0L : count);  // 将日期和对应的发布数量（如果为空则设为0）存入映射关系中
            }
        }

        return Response.success(map);  // 返回包含日期与文章发布数量映射关系的Response对象，状态为成功
    }

    /**
     * 查询仪表盘PV统计信息
     *
     * @return Response对象
     */
    @Override
    public Response findDashboardPVStatistics() {
        // 查询最新一周的统计文章 PVDO 列表
        List<StatisticsArticlePVDO> statisticsArticlePVDOS = articlePVMapper.selectLatestWeekRecords();

        // 创建一个日期-访问量的映射
        Map<LocalDate, Long> pvDateCountMap = Maps.newHashMap();

        // 如果统计文章 PVDO 列表不为空
        if (!CollectionUtils.isEmpty(statisticsArticlePVDOS)){
            // 将统计文章 PVDO 列表中的日期和访问量添加到映射中
            pvDateCountMap = statisticsArticlePVDOS.stream()
                    .collect(Collectors.toMap(StatisticsArticlePVDO::getPvDate, StatisticsArticlePVDO::getPvCount));
        }

        FindDashboardPVStatisticsInfoRspVO vo = null;

        // 创建一个日期列表和访问量列表
        List<String> pvDates = Lists.newArrayList();
        List<Long> pvCounts = Lists.newArrayList();

        // 获取当前日期
        LocalDate currDate = LocalDate.now();

        // 获取上一周的日期
        LocalDate tmpDate = currDate.minusWeeks(1);

        // 遍历日期列表
        for (; tmpDate.isBefore(currDate) || tmpDate.isEqual(currDate); tmpDate = tmpDate.plusDays(1)){
            // 添加日期到日期列表中
            pvDates.add(tmpDate.format(Constants.MONTH_DAY_FORMATTER));

            // 获取日期对应的访问量
            Long pvCount = pvDateCountMap.get(tmpDate);

            // 如果访问量不为空，将其添加到访问量列表中，否则添加0
            pvCounts.add(Objects.isNull(pvCount) ? 0L : pvCount);
        }

        // 构建Response对象
        vo = FindDashboardPVStatisticsInfoRspVO.builder()
                .pvDate(pvDates)
                .pvCounts(pvCounts)
                .build();

        // 返回成功的Response对象
        return Response.success(vo);
    }

}
